<?php
/**
 * Base class to convert a value to an object.
 *
 * @author  Stephan Schmidt <stephan.schmidt@schlund.de>
 * @author  Frank Kleine <frank.kleine@schlund.de>
 */
XJConfLoader::load('converters.ValueConverter',
                   'exceptions.ValueConversionException'
);
/**
 * Base class to convert a value to an object.
 *
 * @package     XJConf
 * @subpackage  converters
 */
abstract class AbstractObjectValueConverter implements ValueConverter
{
    /**
     * Name of the target class
     *
     * @var  string
     */
    protected $className;

    /**
     * Add all attributes using the appropriate setter methods
     *
     * @param   Tag         $tag
     * @param   Definition  $def
     * @param   object      $instance
     * @throws  ValueConversionException
     */
    protected function addAttributesToValue(Tag $tag, TagDefinition $def, $instance)
    {
        $class = new ReflectionClass(get_class($instance));
        // set all attributes
        foreach ($def->getAttributes() as $att) {
            $val = $att->convertValue($tag);
            // attribute has not been set and there is no
            // default value, skip the method call
            if (null === $val) {
                continue;
            }

            try {
                $method = $class->getMethod($att->getSetterMethod($tag));
                $method->invoke($instance, $val);
            } catch (ReflectionException $re) {
                throw new ValueConversionException('Could not set attribute "' . $att->getName() . '" of "' . $this->getType() . '" using "' . $att->getSetterMethod() . '()", exception message: "' . $re->getMessage() . '".');
            }
        }
    }

    /**
     * Add all children to the created instance
     *
     * @param   Tag         $tag
     * @param   Definition  $def
     * @param   object      $instance
     * @throws  ValueConversionException
     */
    protected function addChildrenToValue(Tag $tag, Definition $def, $instance, $ignore = array())
    {
        // traverse all children
        $children = $tag->getChildren();
        if (count($children) == 0) {
            return;
        }

        $class = new ReflectionClass(get_class($instance));
        foreach ($children as $child) {
            if (in_array($child->getName(), $ignore) == true) {
                continue;
            }
            try {
                $class->getMethod($child->getSetterMethod())->invoke($instance, $child->getConvertedValue());
            } catch (ReflectionException $re) {
                throw new ValueConversionException('Could not add child "' . $child->getKey() . '" to "' . $this->getType() . '" using "' . $child->getSetterMethod() . '()", exception message: "' . $re->getMessage() . '".');
            }
        }
    }

    /**
     * returns the type of the converter
     *
     * @return  string
     */
    public function getType()
    {
        return $this->className;
    }
}
?>